package com.yao.shop.service.impl;

import com.yao.shop.common.Page;
import com.yao.shop.enums.OperateEnum;
import com.yao.shop.enums.OrderStateEnum;
import com.yao.shop.enums.StateEnums;
import com.yao.shop.mapper.*;
import com.yao.shop.pojo.*;
import com.yao.shop.pojo.ShopOrder;
import com.yao.shop.pojo.Dto.OrderDto;
import com.yao.shop.pojo.Dto.OrderProductDto;
import com.yao.shop.pojo.ShopProduct;
import com.yao.shop.pojo.ShopUserAddress;
import com.yao.shop.pojo.vo.ShopOrderVo;
import com.yao.shop.service.ShopOrderService;
import com.yao.shop.shiro.LoginUser;
import com.yao.shop.utils.DateUtils;
import com.yao.shop.utils.IdWorker;
import com.yao.shop.utils.ShiroUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ShopOrderServiceImpl implements ShopOrderService {
    @Autowired
    private ShopProductMapper shopProductMapper;
    @Autowired
    private ShopCouponMapper shopCouponMapper;
    @Autowired
    private ShopUserAddressMapper shopUserAddressMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private ShopOrderMapper shopOrderMapper;
    @Autowired
    private ShopOrderItemMapper shopOrderItemMapper;
    @Autowired
    private ShopOrderHistoryMapper shopOrderHistoryMapper;

    @Autowired
    private ShopOrderPayMapper shopOrderPayMapper;
    @Autowired
    private ShopUserMapper shopUserMapper;
    @Autowired
    private ShopUserStatisticMapper shopUserStatisticMapper;

    @Autowired
    private ShopCartItemMapper shopCartItemMapper;
    @Autowired
    private ShopCouponHistoryMapper shopCouponHistoryMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShopOrder createOrder(OrderDto orderDto) {
        // 1. 前端提交订单参数：收货地址编号、商品编号、购买数量、优惠券编号等
        List<OrderProductDto> productDtoList = orderDto.getProductList();
        // 查询商品集合
        List<Long> productIds = productDtoList.stream().map(OrderProductDto::getProductId).collect(Collectors.toList());
        List<ShopProduct> productList = shopProductMapper.getByIds(productIds);
        Long couponId = orderDto.getCouponId();
        Long addressId = orderDto.getAddressId();
        // 查询地址
        ShopUserAddress address = shopUserAddressMapper.get(addressId);
        // 2. 商品扣减库存
        // 3. 计算总金额
        BigDecimal totalMoney = BigDecimal.ZERO;
        // 总积分
        BigDecimal totalPoint = BigDecimal.ZERO;
        for (ShopProduct product : productList) {
            OrderProductDto temp = productDtoList.stream().filter(d -> d.getProductId().equals(product.getId())).findFirst().orElse(null);
            product.setStock(product.getStock() - temp.getCount());
            // 计算该商品需要支付金额
            BigDecimal productMoney = product.getPrice().multiply(new BigDecimal(temp.getCount()));
            // 计算总金额
            totalMoney = totalMoney.add(productMoney);
            // 计算总积分
            BigDecimal point = product.getPoint();
            if (point != null) {
                totalPoint = totalPoint.add(point);
            }
        }
        // 应付金额
        BigDecimal payAmount = totalMoney;
        // 优惠券抵扣金额
        BigDecimal couponAmount = BigDecimal.ZERO;
        // 如果用了优惠券就扣除优惠券的金额
        if (couponId != null) {
            // 查询优惠券
            ShopCoupon shopCoupon = shopCouponMapper.get(couponId);
            if (shopCoupon != null) {
                couponAmount = shopCoupon.getAmount();
                payAmount = totalMoney.subtract(shopCoupon.getAmount());
            }
        }
        // 取出创建人
        LoginUser loginUser = ShiroUtils.getLoginUser();
        ShopOrder order = saveOrder(orderDto, productDtoList, productList, address, totalMoney, totalPoint, payAmount, couponAmount, loginUser);
        // 5. 优惠券状态变更为已使用
        if (orderDto.getCouponId() != null) {
            // 更新优惠券使用数量
            ShopCoupon coupon = shopCouponMapper.get(orderDto.getCouponId());
            coupon.setUseCount(coupon.getUseCount() + 1);
            shopCouponMapper.updateCount(coupon);
            // 优惠券领取历史表数据状态变更为已使用，更新使用时间和订单号
            ShopCouponHistory shopCouponHistory = shopCouponHistoryMapper.getByCouponIdAndUsername(coupon.getId(), loginUser.getUsername());
            shopCouponHistory.setUseStatus(StateEnums.COUPON_NORMAL.getCode());
            shopCouponHistory.setUseTime(DateUtils.newDateTime());
            shopCouponHistory.setOrderId(order.getId());
            shopCouponHistoryMapper.updateToUse(shopCouponHistory);
        }
        // 6. 如果购物车项ID不为空，清空购物车项
        Long cartId = productDtoList.get(0).getCartId();
        if (cartId != null) {
            // 说明是购物车下单，清空这些购物车项
            List<Long> cartIds = productDtoList.stream().map(OrderProductDto::getCartId).collect(Collectors.toList());
            shopCartItemMapper.deleteByIds(cartIds);
        }
        return order;
    }

    private ShopOrder saveOrder(OrderDto orderDto, List<OrderProductDto> productDtoList, List<ShopProduct> productList, ShopUserAddress address, BigDecimal totalMoney, BigDecimal totalPoint, BigDecimal payAmount, BigDecimal couponAmount, LoginUser loginUser) {
        // 4. 存入订单表、订单项表、订单历史表
        ShopOrder order = new ShopOrder();
        order.setId(idWorker.nextId());
        order.setCreateBy(loginUser.getUsername());
        order.setTotalAmount(totalMoney);
        order.setPayAmount(payAmount);
        order.setCouponAmount(couponAmount);
        order.setDeliveryCompany("稽哥快递");
        order.setDeliverySn(idWorker.nextId() + "");
        order.setIntegration(totalPoint.toString());
        order.setReceiverName(address.getName());
        order.setReceiverPhone(address.getPhoneNumber());
        order.setReceiverPostCode("233333");
        order.setReceiverProvince(address.getProvince());
        order.setReceiverCity(address.getCity());
        order.setReceiverRegion(address.getRegion());
        order.setReceiverDetailAddress(address.getDetailAddress());
        order.setNote(orderDto.getNote());
        order.setCouponAmount(BigDecimal.ZERO);
        order.setStatus(2);

        ShopOrderHistory orderHistory = new ShopOrderHistory();
        orderHistory.setId(idWorker.nextId());
        orderHistory.setOrderId(order.getId());
        orderHistory.setOperateMan(OperateEnum.USER.getType());
        orderHistory.setOrderStatus(OrderStateEnum.WAIT_SEND.getCode());
        // 构造订单项
        List<ShopOrderItem> shopOrderItemList = productList.stream().map(p -> {
            ShopOrderItem item = new ShopOrderItem();
            item.setId(idWorker.nextId());
            item.setOrderId(order.getId());
            item.setProductId(p.getId());
            item.setProductPic(p.getPic());
            item.setProductName(p.getName());
            item.setProductBrand(p.getBrandName());
            item.setProductPrice(p.getPrice());
            OrderProductDto temp = productDtoList.stream().filter(d -> d.getProductId().equals(p.getId())).findFirst().orElse(null);
            item.setProductQuantity(temp.getCount());
            item.setProductCategoryId(p.getCategoryId());
            BigDecimal point = p.getPoint();
            if (point == null) {
                point = BigDecimal.ZERO;
            }
            item.setIntegration(point.intValue());
            return item;
        }).collect(Collectors.toList());
        // 订单、订单项、订单历史入库，商品库存扣减
        shopOrderMapper.save(order);
        shopOrderHistoryMapper.save(orderHistory);
        shopOrderItemMapper.saveBatch(shopOrderItemList);
        for (ShopProduct product : productList) {
            shopProductMapper.updateStock(product);
        }
        return order;
    }
    @Override
    public Page<ShopOrderVo> getMyOrder(Page<ShopOrderVo> page) {
        // 分页查询当前登录用户的订单列表
        LoginUser loginUser = ShiroUtils.getLoginUser();
        page.getParams().put("createBy", loginUser.getUsername());
        List<ShopOrder> list = shopOrderMapper.getMyOrder(page);
        Integer count = shopOrderMapper.getMyOrderCount(page);
        // 取出订单ID集合，查询每个订单的订单项信息
        if (!CollectionUtils.isEmpty(list)) {
            List<Long> orderIds = list.stream().map(ShopOrder::getId).collect(Collectors.toList());
            List<ShopOrderItem> itemList = shopOrderItemMapper.getByOrderIds(orderIds);
            List<ShopOrderVo> orderVoList = list.stream().map(o -> {
                ShopOrderVo vo = new ShopOrderVo();
                BeanUtils.copyProperties(o, vo);
                List<ShopOrderItem> orderItems = itemList.stream().filter(i -> i.getOrderId().equals(o.getId())).collect(Collectors.toList());
                vo.setItemList(orderItems);
                return vo;
            }).collect(Collectors.toList());
            page.setList(orderVoList);
        } else {
            page.setList(new ArrayList<>(0));
        }
        page.setTotalCount(count);
        return page;
    }

    @Override
    public ShopOrderVo get(Long id) {
        // 根据id查询订单
        ShopOrder order = shopOrderMapper.get(id);
        ShopOrderVo vo = new ShopOrderVo();
        BeanUtils.copyProperties(order, vo);
        // 根据订单id查询订单项
        List<ShopOrderItem> itemList = shopOrderItemMapper.getByOrderId(id);
        vo.setItemList(itemList);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiveById(Long id) {
        ShopOrder order = shopOrderMapper.get(id);
        order.setStatus(OrderStateEnum.ALREADY_SIGN.getCode());
        order.setConfirmStatus(1);
        shopOrderMapper.changeOrderStatus(order);
        // 存储订单历史
        ShopOrderHistory orderHistory = new ShopOrderHistory();
        orderHistory.setId(idWorker.nextId());
        orderHistory.setOrderId(order.getId());
        orderHistory.setOperateMan(OperateEnum.USER.getType());
        orderHistory.setOrderStatus(OrderStateEnum.ALREADY_SIGN.getCode());
        shopOrderHistoryMapper.save(orderHistory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payById(Long id) {
        ShopOrder order = shopOrderMapper.get(id);
        order.setStatus(OrderStateEnum.WAIT_SEND.getCode());
        shopOrderMapper.updateOrderStatus(order);
        // 存储订单历史
        ShopOrderHistory orderHistory = new ShopOrderHistory();
        orderHistory.setId(idWorker.nextId());
        orderHistory.setOrderId(order.getId());
        orderHistory.setOperateMan(OperateEnum.USER.getType());
        orderHistory.setOrderStatus(OrderStateEnum.ALREADY_SIGN.getCode());
        shopOrderHistoryMapper.save(orderHistory);
    }
    @Override
    public Page<ShopOrder> getByPage(Page<ShopOrder> page) {
        List<ShopOrder> list = shopOrderMapper.getByPage(page);
        Integer count = shopOrderMapper.getCountByPage(page);
        page.setList(list);
        page.setTotalCount(count);
        return page;
    }

    @Override
    public void changeOrderStatus(ShopOrder order) {
        shopOrderMapper.updateOrderStatus(order);
    }
    @Override
    public List<ShopOrderHistory> getHistory(Long id) {
        return shopOrderHistoryMapper.getHistory(id);
    }
}
